/**
 * This library is a thing to realize D2L and DI and AOP on Flex2(ActionScript3).
 * Copyright (C) 2007 Takamasa Seki
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Contributor : Takamasa Seki(takanafu@gmail.com)
 *               http://www.takanafu.com/
 */
 
package com.takanafu.haruframework.d2l.invoker{
	import com.takanafu.core.haru_internal;
	import com.takanafu.haruframework.d2l.invoker.AbstractInvoker;
	import com.takanafu.haruframework.aop.reflect.MethodImpl;
	import com.takanafu.haruframework.aop.AfterReturningAdvice;
	import com.takanafu.haruframework.aop.MethodBeforeAdvice;
	import com.takanafu.haruframework.aop.ThrowsAdvice;
	import mx.collections.ArrayCollection;
	import com.takanafu.haruframework.aop.reflect.ClassImpl;
	import mx.core.Singleton;
	import com.takanafu.haruframework.beans.BeanConstant;
	
	use namespace haru_internal;
	
	public class InvokerFactory{
		static public function getInvoker(obj:Object):AbstractInvoker{
			var func:MethodImpl = obj["method"];
			var invoker:AbstractInvoker = null;
			var ivc:IInvocationProxy = Singleton.getInstance("com.takanafu.haruframework.d2l.invoker::IInvocationProxy") as IInvocationProxy;
			
			if(func != null){
				var name:String = func.getName();
				var pointcutAdvisorMap:Object = ivc.getPointcutAdvisorMap();
				invoker = new AbstractInvoker(func);
				
				if(obj.interceptorNames != null){
					var advs:Array = obj.interceptorNames;
					var advcnt:int = advs.length;
					
					for(var ai:int;ai < advcnt;ai++){
						var advname:String = advs[ai];
						var adv:Object = ivc.getBean(advname,true);
						
						if(adv != null){
							var info:XML = adv["info"] as XML;
							
							if(info != null){
								if(info.hasOwnProperty("@priority") == true){
									invoker.addAdvisor(adv["classImpl"],info.@priority);
								}else{
									invoker.addAdvisor(adv["classImpl"],BeanConstant.PRIORITY_DEFAULT);
								}
							}
						}
					}
				}
				for(var prop:Object in pointcutAdvisorMap){
					if(pointcutAdvisorMap[prop]["type"] == "RegexpMethod"){
						var ary:ArrayCollection = pointcutAdvisorMap[prop]["patterns"];
						var cnt:Number = ary != null ? ary.length : 0;
						
						for(var i:Number = 0;i < cnt;i++){
							var ptn:RegExp = new RegExp(ary.getItemAt(i).toString());
							
							if(ptn.test(name) == true){
								var rmadv:ClassImpl = pointcutAdvisorMap[prop]["advice"]["bean"] as ClassImpl;
								
								invoker.addAdvisor(rmadv,pointcutAdvisorMap[prop]["advice"]["priority"]);
								/*
								var rmadv:ClassImpl = pointcutAdvisorMap[prop]["advice"]["bean"] as ClassImpl;
								var beforeAdvice:MethodBeforeAdvice = rmadv.getClass() as MethodBeforeAdvice;
								var afterAdvice:AfterReturningAdvice = rmadv.getClass() as AfterReturningAdvice;
								var throwsAdvice:ThrowsAdvice = rmadv.getClass() as ThrowsAdvice;
								var ret:*;
								
								try{
									if(beforeAdvice != null){
										ret = beforeAdvice.before(func,null,null);
									}
									ret = func.getFunction().call(func,event);
								}catch(e:Error){
									throwsAdvice.afterThrowing(func,null,null,e);
								}finally{
									if(afterAdvice != null){
										afterAdvice.afterReturning(ret,func,null,null);
									}
								}
								*/
							}
						}
					}
				}
			}
			return invoker;
		}
	}
}